package data

import (
	"context"
	"errors"
	"fmt"
	"time"

	"gitlab.cqcb.com/shangyou_mic/dscm-approve-api-pb/api/roses/v1"

	"gorm.io/gorm"
)

type AccountSchema struct {
	db *DB
}

func NewAccountSchema(db *DB) (*AccountSchema, error) {
	account := &AccountSchema{
		db: db,
	}
	return account, nil
}

// CreateUser 创建账户
func (s *AccountSchema) CreateUser(ctx context.Context, user *User, dbx ...*gorm.DB) error {
	if user == nil || (user.Username == nil || *user.Username == "") || (user.Mobile == nil || *user.Mobile == "") {
		return errors.New("缺少必填参数")
	}
	return s.db.Transaction(s.db.DB(dbx...), func(tx *gorm.DB) error {
		tx = tx.WithContext(ctx)
		exists := &User{}
		err := s.db.Table(user, tx).
			Scopes(
				sqlEqual("username", *user.Username),
				sqlEqual("mobile", *user.Mobile),
				func(db *gorm.DB) *gorm.DB {
					return db.Select("id")
				},
			).
			First(exists)
		if !errors.Is(err, gorm.ErrRecordNotFound) {
			return err
		}
		if exists.Id > 0 {
			return errors.New("该用户已存在")
		}
		timestamp := time.Now().Unix()
		if user.CreatedAt <= 0 {
			user.CreatedAt = timestamp
		}
		if user.UpdatedAt != user.CreatedAt {
			user.UpdatedAt = timestamp
		}
		user.State = 1
		_, err = s.db.Insert(tx, exists.TableName(), user, nil)
		if err != nil {
			return err
		}
		return nil
	})
}

// UserInfo 查询账户信息
func (s *AccountSchema) UserInfo(ctx context.Context, userId int64, dbx ...*gorm.DB) (*User, error) {
	notFound := fmt.Errorf("account(%d) is not found", userId)
	if userId <= 0 {
		return nil, notFound
	}
	db := s.db.DB(dbx...)
	lists := make([]*User, 0)
	err := db.Model(&User{}).Scopes(sqlEqual("id", userId), sqlContext(ctx)).Select("*").Where("deleted_at = 0").Limit(1).Find(&lists).Error
	if err != nil {
		return nil, err
	}
	if len(lists) == 0 {
		return nil, notFound
	}
	return lists[0], nil
}

// ServerGetUser 查询账户信息
func (s *AccountSchema) ServerGetUser(ctx context.Context, req *v1.FxUser, dbx ...*gorm.DB) (*User, error) {
	db := s.db.DB(dbx...)
	lists := make([]*User, 0)
	scopes := make([]func(db *gorm.DB) *gorm.DB, 0, 2)
	if req.Id <= 0 && (req.Username == nil || *req.Username == "") && (req.Mobile != nil || *req.Mobile == "") && (req.Email == nil || *req.Email == "") {
		return nil, nil
	}
	if req.Id > 0 {
		scopes = append(scopes, sqlEqual("id", req.Id))
	}
	if req.GetUsername() != "" {
		scopes = append(scopes, sqlEqual("username", req.GetUsername()))
	}
	if req.GetMobile() != "" {
		scopes = append(scopes, sqlEqual("mobile", req.GetMobile()))
	}
	if req.GetEmail() != "" {
		scopes = append(scopes, sqlEqual("email", req.GetEmail()))
	}
	scopes = append(scopes, sqlContext(ctx))
	err := db.Model(&User{}).Scopes(scopes...).Select("*").Where("deleted_at = 0").Limit(1).Find(&lists).Error
	if err != nil {
		return nil, err
	}
	if len(lists) == 0 {
		return nil, nil
	}
	return lists[0], nil
}

// VerifyUserState 校验账户状态是否正常
func (s *AccountSchema) VerifyUserState(user *User) error {
	if user == nil {
		return errors.New("user is nil")
	}
	if user.DeletedAt > 0 {
		return errors.New("账户不存在")
	}
	if user.State != 1 {
		return fmt.Errorf("account(%d) abnormal", user.Id)
	}
	return nil
}

type UpdateUserIntegralReq struct {
	*UserIntegral
}

// UpdateUserIntegral 更新账户积分
func (s *AccountSchema) UpdateUserIntegral(ctx context.Context, integral *UpdateUserIntegralReq, dbx ...*gorm.DB) error {
	if integral.UserIntegral == nil || integral.UserId <= 0 || integral.ChangeAmount == 0 {
		return nil
	}
	user, err := s.UserInfo(ctx, integral.UserId, dbx...)
	if err != nil {
		return err
	}
	err = s.VerifyUserState(user)
	if err != nil {
		return err
	}
	if integral.ChangeAmount < 0 {
		// 扣用户积分时 如果 用户的积分余额不足 如何处理
	}
	db := s.db.DB(dbx...)

	rows := int64(0)

	// 扣除积分
	err = db.Transaction(func(tx *gorm.DB) error {
		rows, err = s.db.Insert(tx, &UserIntegral{}, integral.UserIntegral, nil)
		if err != nil {
			return err
		}
		if rows <= 0 {
			// todo
			return nil
		}

		return nil
	})
	return nil
}
